package edu.cug.water.crawler.job.task.ministerial;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import edu.cug.water.crawler.common.annotation.BeanField;
import edu.cug.water.crawler.common.constant.Constant;
import edu.cug.water.crawler.common.constant.EsConstants;
import edu.cug.water.crawler.common.exception.RRException;
import edu.cug.water.crawler.common.utils.DateUtils;
import edu.cug.water.crawler.common.utils.EsUtils;
import edu.cug.water.crawler.job.entity.ministerial.NationalSurfaceWaterQuality;
import edu.cug.water.crawler.job.request.RequestUtil;
import edu.cug.water.crawler.job.task.ITask;
import edu.cug.water.crawler.job.utils.AbstractCrawlerTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * url：http://106.37.208.243:8070/GJZ/Business/Publish/Main.html
 * 1998个国控水站
 */
@Slf4j
@Component("job:nationalSurfaceWaterQuality")
public class NationalSurfaceWaterQualityTask extends AbstractCrawlerTask<NationalSurfaceWaterQuality> implements ITask {

    private static final String REGEX_STR = "title='所在地市:(.*);所属河流:(.*)'>(.*)</span>";
    private static final String REGEX_NUMBER = "title='原始值：(.*)'>";
    static final Pattern patternStr = Pattern.compile(REGEX_STR);
    static final Pattern patternNumber = Pattern.compile(REGEX_NUMBER);


    @Autowired
    private EsUtils esUtils;

    @Autowired
    private RequestUtil requestUtil;

    @Override
    public int run(String params) throws IOException {
        init();
        ResponseEntity<String> response = getRequestBody();

        List<NationalSurfaceWaterQuality> results = getDataFromStr(response.getBody());
        log.info("{} converts results：{}", getClass().getName(), results.size());

        String s = esUtils.addDocuments(EsConstants.TypeConstant.NATIONAL_SURFACE_WATER_QUALITY.getValue(), results);

        Boolean aBoolean = esUtils.statusJudge(s);

        if (!aBoolean) {
            throw new RRException(Constant.LogConstants.THE_PROCESS_OF_ES_STORE_FAILED.getValue());
        }
        return results.size();
    }

    @Override
    protected void init() {
        super.init();
        url = "https://szzdjc.cnemc.cn:8070/GJZ/Ajax/Publish.ashx";

        headers.set("Host", "szzdjc.cnemc.cn:8070");
        headers.set("Connection", "keep-alive");
        headers.set("Content-Length", "68");
        headers.set("Accept", "application/json, text/javascript, */*; q=0.01");
        headers.set("X-Requested-With", "XMLHttpRequest");
        headers.set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        headers.set("Origin", "https://szzdjc.cnemc.cn:8070");
        headers.set("Referer", "https://szzdjc.cnemc.cn:8070/GJZ/Business/Publish/RealDatas.html");
        headers.set("Accept-Encoding", "gzip, deflate");
        headers.set("Accept-Language", "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7");
        headers.set("Cookie", "Mo5Ukf9ZObndO=5.O1PbqCz0SahESnkKS2SMXBN0Q58m_K4KinoI8.Uq.tB9c41DrY7dolZ1CgU2LURjYQzwN0uMiSFRrASv0UkWa; Hm_lvt_0b8b0a2a4a45cbaaa6f549dcad3329a6=1661497389; Hm_lvt_aadbcc83cc37610f46f503983c444e90=1661497389; Hm_lpvt_aadbcc83cc37610f46f503983c444e90=1661497407; Hm_lpvt_0b8b0a2a4a45cbaaa6f549dcad3329a6=1661497407");

        multiValueMap.add("AreaID", "");
        multiValueMap.add("RiverID", "");
        multiValueMap.add("MNName", "");
        multiValueMap.add("PageIndex", "1");
        multiValueMap.add("PageSize", "2000");
        multiValueMap.add("action", "getRealDatas");
    }

    @Override
    public ResponseEntity<String> getRequestBody() {
        return requestUtil.post(url, headers, multiValueMap);
    }

    @Override
    public List<NationalSurfaceWaterQuality> getDataFromStr(String jsonStr) {
        if (StringUtils.isEmpty(jsonStr))
            throw new RRException(getClass().getName() + Constant.LogConstants.RESPONSE_IS_NULL.getValue());

        List<NationalSurfaceWaterQuality> results = new ArrayList<>();

        JSONObject response = (JSONObject) JSONObject.parse(jsonStr);
        JSONArray data = (JSONArray) response.get("tbody");

        for (int i = 0; i < data.size(); i++) {
            JSONArray items = data.getJSONArray(i);

            NationalSurfaceWaterQuality quality = new NationalSurfaceWaterQuality();
            Field[] declaredFields = quality.getClass().getDeclaredFields();

            List<Field> list = new ArrayList<Field>();
            for (Field field : declaredFields) {
                if (field.getAnnotation(BeanField.class) != null) list.add(field);
            }

            list.sort(Comparator.comparingInt(m -> m.getAnnotation(BeanField.class).order()));

            for (int j = 0; j < list.size(); j++) {
                try {
                    Field item = list.get(j);
                    item.setAccessible(true);
                    int index = item.getAnnotation(BeanField.class).dealNumber();
                    if (index != -1 && items.getString(j) != null) {
                        item.set(quality, methodIndex(items.getString(j), index).trim());
                    } else {
                        item.set(quality, items.getString(j) == null ? "":items.getString(j).trim());
                    }
                } catch (IllegalAccessException e) {
                    log.error("{} {}", getClass().getName(), Constant.LogConstants.FIELD_ASSIGNMENT_ILLEGAL_ACCESS.getValue());
                    throw new RRException(Constant.LogConstants.FIELD_ASSIGNMENT_ILLEGAL_ACCESS.getValue() + e.getMessage());
                }
            }
            quality.setCreateTime(DateUtils.formatDateTime(new Date()));
            results.add(quality);
        }

        return results;
    }




    private static String methodIndex(String str, int idx) {
        if (idx == 1) return dealString(str);
        if (idx == 2) return dealNumber(str);
        if (idx == 3) return dealDate(str);
        return null;
    }

    private static String dealString(String str) {
        Matcher matcher = patternStr.matcher(str.trim());
        if (matcher.find()) {
            str = matcher.group(1) + "-" + matcher.group(2) + "-" + matcher.group(3);
            str = str.replace("&#10", "");
        }
        return str.trim();
    }

    private static String dealNumber(String str) {
        Matcher matcher = patternNumber.matcher(str.trim());
        if (matcher.find()) {
            str = matcher.group(1);
        }
        return str.trim();
    }

    private static String dealDate(String str) {
        str = Calendar.getInstance().get(Calendar.YEAR) + "-" + str.trim();

        return str.trim();
    }


    public static void main(String[] args) {
        NationalSurfaceWaterQualityTask nationalSurfaceWaterQualityTask = new NationalSurfaceWaterQualityTask();
        try {
            nationalSurfaceWaterQualityTask.run(null);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
